#ifndef AVALON_TIMER_HPP
#define AVALON_TIMER_HPP
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/signals2.hpp>
#pragma warning(disable : 4267)
#include <boost/thread.hpp>
#pragma warning(default : 4267)
#include "Avalon/Threading/Threading.hpp"

namespace boost {
namespace system {
  class error_code;
}
}

namespace Avalon {
namespace Threading {

  /*! \class Timer
   *  \brief Emits signals at specified time intervals.
   *  \author Kamal Mansouri <kranar@hotmail.com>
   */
  class Timer {
    public:

      //! Signals that a Timer's interval expired.
      typedef boost::signals2::signal<void ()> ExpiredSignal;

      //! Constructs a Timer.
      Timer();

      virtual ~Timer();

      //! Returns the time interval.
      boost::posix_time::time_duration GetInterval();

      //! Starts the Timer.
      /*!
        \param interval The time interval before expiring.
        \param repeat Whether to repeat this timer until The Stop method is
                      invoked.
        \param startTime The time to start this Timer.
      */
      void Start(boost::posix_time::time_duration interval,
        bool repeat = true, boost::posix_time::time_duration startTime =
        boost::posix_time::time_duration());

      //! Stops the Timer from posting any further signals.
      void Stop();

      //! Connects to the ExpiredSignal.
      /*!
        \param slot The slot to connect.
        \return The <i>slot</i>'s connection to the signal.
      */
      boost::signals2::connection ConnectExpiredSignal(
        const ExpiredSignal::slot_type& slot);

    private:
      class Manager;
      class TimerThread;
      boost::mutex m_mutex;
      boost::condition_variable m_completeCondition;
      boost::posix_time::time_duration m_interval;
      bool m_repeat;
      bool m_running;
      ExpiredSignal m_expiredSignal;
      void* m_timerService;

      void StartWait();
      void HandleTrigger(const boost::system::error_code& error);
  };
}
}

#endif // AVALON_TIMER_HPP
